package pcloud.client;

import pcloud.client.remoteservice.FileService;
import pcloud.client.scheduler.TaskScheduler;
import pcloud.client.util.ClientIdentifier;
import pcloud.client.util.FileResourceInfo;
import pcloud.client.util.FileSystemDB;
import pcloud.client.util.GlobalConfig;
import pcloud.client.util.TreeDB;
import pcloud.client.watcher.ClientWatcher;
import pcloud.client.watcher.FTPServerWatcher;
import pcloud.client.watcher.PollClientWatcher;
import pcloud.client.watcher.ServerWatcher;
import org.apache.log4j.Logger;

public class PCloudClient
{
	private ClientWatcher clientWatcher;
	private ServerWatcher serverWatcher;
	
	private TreeDB<FileResourceInfo> localDB;
	private TaskScheduler taskScheduler;
	private FileService remoteService;
	private static Logger logger = Logger.getLogger(PCloudClient.class);

	public PCloudClient()
	{
		checkConfig();
		localDB = new FileSystemDB<FileResourceInfo>();
		taskScheduler = new TaskScheduler();
		clientWatcher = new PollClientWatcher(taskScheduler, localDB);
		serverWatcher = new FTPServerWatcher(taskScheduler,localDB);
	}

	private void checkConfig()
	{
		GlobalConfig.getInstance();
	}

	private void fullSyncOnce()
	{
		serverWatcher.syncOnce();
		//clientWatcher.syncOnce();
	}

	private boolean isFirstTimeStart()
	{
		return ClientIdentifier.isFirstCreate();
	}

	private void startClientWatcher()
	{
		clientWatcher.start();
	}

	private void startServerWatcher()
	{
		serverWatcher.start();
	}

	public void startSync()
	{
		logger.info("before start remote service");
		remoteService = GlobalConfig.initRemoteService();
		if (remoteService==null){
			return;
		}
		if (isFirstTimeStart()) {
			logger.info("before first start full sync");
			fullSyncOnce();
		}
		logger.info("before startTaskScheduler()");
		startTaskScheduler();
		logger.info("before startClientWatcher()");
		startClientWatcher();
		logger.info("before startServerWatcher()");
		try {
			Thread.sleep(150000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		startServerWatcher();
	}

	private void startTaskScheduler()
	{
		taskScheduler.start();
	}

	public void stopSync()
	{
		logger.info("before stopServerWatcher()");
		stopServerWatcher();
		logger.info("before stopClientWatcher()");
		stopClientWatcher();
		logger.info("before stopTaskScheulder()");
		stopTaskScheulder();
		logger.info("before releaseRemoteService()");
		GlobalConfig.releaseRemoteService();
		logger.info("waiting for all threads end...");
		waitingForAllThreadsEnd();
		remoteService.release();
	}

	private void waitingForAllThreadsEnd()
	{
		try {
			serverWatcher.getWorkingThread().join();
		} catch (InterruptedException e) {
			logger.error("wait ServerWatcher thread failed! ");
		}
		try {
			clientWatcher.getWorkingThread().join();
		} catch (InterruptedException e) {
			logger.error("wait ClientWatcher thread failed! ");
		}
		try {
			taskScheduler.getWorkingThread().join();
		} catch (InterruptedException e) {
			logger.error("wait scheduler thread failed! ");
		}
	}

	private void stopTaskScheulder()
	{
		taskScheduler.stop();
	}
	
	private void stopClientWatcher()
	{
		clientWatcher.stop();
	}

	private void stopServerWatcher()
	{
		serverWatcher.stop();
	}

	public TreeDB<FileResourceInfo> getLocalDb()
	{
		return localDB;
	}

}
